<?php

namespace App\Http\Controllers;

use DB;
use Illuminate\Http\Request;
use Validator;

use Unirest\Request AS API;
use Ptime3\Functions\Queue;

class SystemController extends Controller
{
    private function preInner($userId, $campusId, $systemId){
        //模拟访问
        $apiUrl   = DB::table("cp_system")->where("id",$systemId)->value("api_url");
        $response = API::get($apiUrl."/pre",[],["campus_id"=>$campusId]);
        if($response->code != 200)
            return $this::innerResponse(true,"apiTimeOut","访问超时");

        //保存数据
        $responseBody = $response->body;
        if(!isset($responseBody->error))
            return $this::innerResponse(true,"apiError","访问出错");

        $userSystemResult = DB::table("cp_user_system")
            ->select("id","username","password","type")
            ->where("user_id",$userId)
            ->where("system_id",$systemId)
            ->where("campus_id",$campusId)
            ->first();

        if(!$responseBody->error && !empty($userSystemResult)){
        	$responseBody->result->username = $userSystemResult->username;
        	$responseBody->result->password = !empty($userSystemResult->username)?1:"";
            if(!empty($responseBody->result->type_row))
        	   $responseBody->result->type  = $userSystemResult->type;
            if(!empty($responseBody->result->code_row)){
                $code2txtServer   = env("SERVICE_CODE_ADDRESS");
                $code2txtRequst   = ["code_row"=>$responseBody->result->code_row,"system_id"=>$systemId];
                $code2txtResponse = API::post($code2txtServer,[],$code2txtRequst);
                if($code2txtResponse->code == 200 && strlen($code2txtResponse->body)==4)
                    $responseBody->result->code = $code2txtResponse->body;
            }
        }

        if(!$responseBody->error){
            $data = [
                "token" => !empty($responseBody->result->token)?$responseBody->result->token:"",
                "code" =>  !empty($responseBody->result->code)?$responseBody->result->code:""
            ];
            if(!empty($userSystemResult)){
                DB::table("cp_user_system")->where("id",$userSystemResult->id)->update($data);
            }else{
                $data["user_id"]   = $userId;
                $data["system_id"] = $systemId;
                $data["campus_id"] = $campusId;
                DB::table("cp_user_system")->insert($data);
            }
        }

        //return "<img src='".$responseBody->result->code_row."' />".(isset($responseBody->result->code)?$responseBody->result->code:"");
        return (array)$responseBody;
    }

    private function loginInner($input, $userId, $campusId, $systemId){
        //参数检验
        $validator = Validator::make($input,
            [
                'username'   => 'string|min:1',
                'password'   => 'string|min:1',
                'code'       => 'string|min:1',
                'token'      => 'string|min:1'
            ]
        );
        if($validator->fails())
            return $this::innerResponse(true,$validator->messages(),"paramError");

    	//构造数据
        $userSystemResult = DB::table("cp_user_system")
        	->select("id","username","password","code","token","type")
        	->where("user_id",$userId)
        	->where("system_id",$systemId)
            ->where("campus_id",$campusId)
        	->first();

        if(!empty($userSystemResult)){
        	if(empty($input["username"]))
        		$input["username"] = $userSystemResult->username;
        	if(empty($input["code"]))
        		$input["code"]    = $userSystemResult->code;
            if(empty($input["token"]))
                $input["token"]    = $userSystemResult->token;
        	if(empty($input["type"]))
        		$input["type"]     = $userSystemResult->type;
        	if(empty($input["password"]) || $input["password"] == "1")
        		$input["password"] = app("crypt")::decrypt($userSystemResult->password);
        }

        //模拟访问
        $apiUrl   = DB::table("cp_system")->where("id",$systemId)->value("api_url");
        $response = API::post($apiUrl."/login",[],$input);
        if($response->code != 200)
            return $this::innerResponse(true,"apiTimeOut","访问超时");

        //保存记录
        $responseBody = $response->body;
        if(!isset($responseBody->error))
        	return $this::innerResponse(true,"apiError","访问出错");

        if($responseBody->error)
            $responseBody->result = $this::preInner($userId, $campusId, $systemId)["result"];

        if(!$responseBody->error){
            if(!empty($input["password"])) $input["password"] = app("crypt")::encrypt($input["password"]);
        	$data = [
    			"username"  => !empty($input["username"])?$input["username"]:"",
    			"password"  => !empty($input["password"])?$input["password"]:"",
    			"token"     => !empty($input["token"])?$input["token"]:"",
    			"type"      => !empty($input["type"])?$input["type"]:""
    		];

        	if(!empty($userSystemResult)){
        		DB::table("cp_user_system")->where("id",$userSystemResult->id)->update($data);
        	}else{
        		$data["user_id"]   = $userId;
        		$data["system_id"] = $systemId;
                $data["campus_id"] = $campusId;
        		DB::table("cp_user_system")->insert($data);
        	}
            $responseBody->result = "登录成功！";
            //存储数据
            if(empty($userSystemResult) || empty($userSystemResult->intro)){
                Queue::put("restapi",["post","campus","user/$userId/campus/$campusId/system/$systemId/intro/store",[]]);
            }
        }

        return (array)$responseBody;
    }

    private function apiInner($input, $userId, $campusId, $systemId, $apiPath){
        //参数检验
        $validator = Validator::make($input,
            [
                'method'      => 'in:GET,POST,PUT,DELETE',
                'path'        => 'string|min:1',
                'query'       => 'array'
            ]
        );
        if($validator->fails())
            return $this::innerResponse(true,$validator->messages(),"paramError");

        //构造参数
        if($apiPath!="api"){
            $method = "POST";
            $path   = $apiPath;
            $query  = $input;
        }else{
            $method = !empty($input["method"])?$input["method"]:"GET";
            $path   = !empty($input["path"])?$input["path"]:"";
            $query  = !empty($input["query"])?$input["query"]:"";
        }

        $query["token"] = DB::table("cp_user_system")
            ->where("user_id",$userId)
            ->where("system_id",$systemId)
            ->where("campus_id",$campusId)
            ->value("token");

        //模拟访问
        $apiUrl   = DB::table("cp_system")->where("id",$systemId)->value("api_url");
        if(strtoupper($method) == "PUT")
                $query = \Unirest\Request\Body::form($query);
        $response = API::$method($apiUrl."/".$path,[],$query);

        if($response->code != 200)
            return $this::innerResponse(true,$apiUrl."/"." ".$path." ".$systemId." ".$campusId." ".$query["token"],"访问超时");

        $responseBody = $response->body;

        if(!isset($responseBody->error))
            return $this::innerResponse(true,"apiError","访问出错");

        //token过期
        if($responseBody->error && $responseBody->result == "tokenTimeOut")
            return $this->processTokenTimeOut($input, $userId, $campusId, $systemId, $apiPath);

        return (array)$responseBody;
    }

    private function processTokenTimeOut($input, $userId, $campusId, $systemId, $apiPath){
        $preResult = $this->preInner($userId, $campusId, $systemId);
        if(!$preResult["error"]
            && !empty($preResult["result"]->username)
            && !(isset($preResult["result"]->code) && empty($preResult["result"]->code))
        ){
            $loginResult = $this->loginInner([],$userId, $campusId, $systemId);
            if($loginResult["error"]) return $loginResult;
            return $this->apiInner($input,$userId, $campusId, $systemId, $apiPath);
        }

        if(!$preResult["error"]){
            $preResult["error"]   = true;
            $preResult["result"]  = "tokenTimeOut";
            $preResult["message"] = "请重新登录";
            return $preResult;
        }

        return $preResult;
    }

    public function pre($userId, $campusId, $systemId){
        $preResult = $this->preInner($userId, $campusId, $systemId);
        return $this::jsonResponse($preResult["error"]??true,$preResult["result"]??"",$preResult["message"]??"");
    }
    public function login(Request $request,$userId, $campusId, $systemId){
        $input       = $request->all();
        $loginResult = $this->loginInner($input, $userId, $campusId, $systemId);
        return $this::jsonResponse($loginResult["error"]??true,$loginResult["result"]??"",$loginResult["message"]??"");
    }

    public function apiWithSystemCat(Request $request, $userId, $systemCatName, $apiPath){
        $input = $request->all();

        $systemIdHash = ["edu"=>1,"library"=>2];
        if(!isset($systemIdHash[$systemCatName]))
            return $this::jsonResponse(true,"systemCatNull","");

        $systemCatId = $systemIdHash[$systemCatName];

        $systemResult = DB::table("cp_user_system")
          ->select("cp_user_system.campus_id","cp_user_system.system_id")
          ->leftJoin("cp_system","cp_system.id","=","cp_user_system.system_id")
          ->where("cp_user_system.user_id",$userId)
          ->where("cp_user_system.password","!=","")
          ->where("cp_system.cat_id",$systemCatId)
          ->orderBy("cp_user_system.id","DESC")
          ->first();

        if(empty($systemResult))
            return $this::jsonResponse(true,"tokenNull","请登录");

        $campusId = $systemResult->campus_id;
        $systemId = $systemResult->system_id;

        $apiResult = $this->apiInner($input, $userId, $campusId, $systemId, $apiPath);
        return $this::jsonResponse($apiResult["error"]??true,$apiResult["result"]??"",$apiResult["message"]??"");
    }

    public function api(Request $request, $userId, $campusId, $systemId, $apiPath){
        $input = $request->all();
        if(empty($input["notoken"])){
            $userSystemToken = DB::table("cp_user_system")
                ->where("user_id",$userId)
                ->where("system_id",$systemId)
                ->where("campus_id",$campusId)
                ->value("token");

            if(empty($userSystemToken))
                return $this::jsonResponse(true,"tokenNull","请登录");
        }

        $apiResult = $this->apiInner($input, $userId, $campusId, $systemId, $apiPath);
        return $this::jsonResponse($apiResult["error"]??true,$apiResult["result"]??"",$apiResult["message"]??"");
    }

    public function introStore($userId, $campusId, $systemId){
        
        $token = DB::table("cp_user_system")
            ->where("user_id",$userId)
            ->where("system_id",$systemId)
            ->where("campus_id",$campusId)
            ->value("token");
        if(empty($token))
            return $this::jsonResponse(true,"tokenNull","请登录");

        //模拟访问
        $apiUrl   = DB::table("cp_system")->where("id",$systemId)->value("api_url");
        $response = API::post($apiUrl."/intro",[],["token"=>$token]);

        if($response->code != 200)
            return $this::jsonResponse(true,"apiTimeOut","访问超时");

        $responseBody = $response->body;

        if(!isset($responseBody->error))
            return $this::jsonResponse(true,"apiError","访问出错");

        if($responseBody->error)
            return (array)$responseBody;

        //存储数据
        $intro = json_encode($responseBody->result);
        $userSystemUpdateResult = DB::table("cp_user_system")
            ->where("user_id",$userId)
            ->where("system_id",$systemId)
            ->where("campus_id",$campusId)
            ->update(["intro"=>$intro]);

        return $this::jsonResponse(false,$userSystemUpdateResult);
    }
}